/**
 * @author zliming
 */


var ctx;
var speed = 8;

var CFruit = new Class({
	Extends : CImage,
    initialize: function(type, x, y){
        this.parent("fruit_" + type + ".png");
        this.type = type;
        this.x = x;
        this.y = y;
    },
    
    Type: function(type){
        this.type = type;
        this.Src("fruit_" + type + ".png");
    },
    
    OnDraw: function(){
        this.parent();
    },
    mx: 0,
    my: 0,
    type: 0,
});

var FruitBox = new Class({
    initialize: function(){
        this.back = new Image();
        this.back.src = "back.png";
        this.swap0 = {
            x: 0,
            y: 0
        };
        this.swap1 = {
            x: 0,
            y: 0
        };
        this.to_clear = Array2D(8, 9);
        this.box = Array2D(8, 9);
        this.drop = new Array();
        this.g = 0;
        this.NewFruitBox = function(x, y){
            return new CFruit($random(0, 7), x * 40, y * 42);
        };
        
        for (var i = 0; i < 8; i++) {
            for (var j = 0; j < 9; j++) {
                this.box[i][j] = this.NewFruitBox(i, j);
            }
        }
        if (this.CheckClean()) {
            this.ClearBox();
            this.FillUpNewFruit();
        }
    },
    ClearBox: function(){
        for (var x = 0; x < 8; x++) {
            for (var y = 0; y < 9; y++) {
                if (this.to_clear[x][y] != undefined) {
                    this.box[x][y] = null;
                }
            }
        }
    },
    MoveFruit: function(f){
        if (f.x > f.mx) {
            f.x -= Math.min(speed, f.x - f.mx);
        } else if (f.x < f.mx) {
            f.x += Math.min(speed, f.mx - f.x);
        }
        
        if (f.y > f.my) {
            f.y -= Math.min(speed, f.y - f.my);
        } else if (f.y < f.my) {
            f.y += Math.min(speed, f.my - f.y);
        }
    },
    SwapType: function(x0, y0, x1, y1){
        var tmp = this.box[x0][y0];
        this.box[x0][y0] = this.box[x1][y1];
        this.box[x1][y1] = tmp;
    },
    OnDraw: function(){
        ctx.drawImage(this.back, 0, 0);
        for (var i = 0; i < 8; i++) {
            for (var j = 0; j < 9; j++) {
                if (this.box[i][j] != null) {
                    this.box[i][j].OnDraw();
                }
            }
        }
        for (var i = 0; i < this.drop.length; i++) {
            this.drop[i].OnDraw();
        }
        myMouse.OnDraw();
    },
    SwapPoint: function(x0, y0, x1, y1){
        var f0 = this.box[x0][y0];
        var f1 = this.box[x1][y1];
        f0.mx = f1.x;
        f0.my = f1.y;
        f1.mx = f0.x;
        f1.my = f0.y;
        this.swap0.x = x0;
        this.swap0.y = y0;
        this.swap1.x = x1;
        this.swap1.y = y1;
    },
    FillUpNewFruit: function(){
        var x, y, l;
        for (x = 8 - 1; x >= 0; x--) {
            for (y = 9 - 1; y >= 0; y--) {
                if (this.box[x][y] == null) 
                    break;
            }
            
            l = y;
            for (; y >= 0; y--) {
                if (this.box[x][y] != null) {
                    var f = this.box[x][y];
                    f.x = x * 40;
                    f.y = y * 42;
                    f.my = l * 42;
                    this.drop.push(f);
                    l--;
                    this.box[x][y] = null;
                }
            }
            for (; l >= 0; l--, y--) {
                var f = this.NewFruitBox(x, y);
                f.my = l * 42;
                this.drop.push(f);
            }
        }
        this.drop.reverse();
        this.g = 0;
        myMouse.state = GameState.MoveDown;
    },
    MoveDownFruit: function(){
        this.g += 2;
        for (var i = this.drop.length - 1; i >= 0; i--) {
            var f = this.drop[i];
            f.y = Math.min(f.my, f.y + this.g);
            if (f.y == f.my) {
                this.box[(f.x / 40).toInt()][(f.my / 42).toInt()] = f;
                this.drop.splice(i, 1);
            }
        }
    },
    OnUpdate: function(){
        switch (myMouse.state) {
            case GameState.TestSwap:
                var f = this.box[this.swap0.x][this.swap0.y];
                if (f.x == f.mx && f.y == f.my) {
                    this.SwapType(this.swap0.x, this.swap0.y, this.swap1.x, this.swap1.y);
                    if (!this.CheckClean()) {
                        this.SwapPoint(this.swap0.x, this.swap0.y, this.swap1.x, this.swap1.y);
                        myMouse.state = GameState.MoveBack;
                    } else {
                        this.ClearBox();
                        this.FillUpNewFruit();
                        break;
                    }
                } else {
                    this.MoveFruit(f);
                    this.MoveFruit(this.box[this.swap1.x][this.swap1.y]);
                }
                break;
            case GameState.MoveBack:
                var f1 = this.box[this.swap0.x][this.swap0.y];
                if (f1.x == f1.mx && f1.y == f1.my) {
                    this.SwapType(this.swap0.x, this.swap0.y, this.swap1.x, this.swap1.y);
                    myMouse.state = GameState.None;
                } else {
                    this.MoveFruit(f1);
                    this.MoveFruit(this.box[this.swap1.x][this.swap1.y]);
                }
                break;
            case GameState.MoveDown:
                if (this.drop.length > 0) {
                    this.MoveDownFruit();
                } else {
                    myMouse.state = GameState.None;
                    if (this.CheckClean()) {
                        this.ClearBox();
                        this.FillUpNewFruit();
                    }
                }
                break;
        }
    },
    CheckClean: function(){
        this.to_clear = Array2D(8, 9);
        
        var sames, t;
        var result = false;
        
        for (var x = 0; x < 8; x++) {
            for (var y = 0; y < 9; y++) {
                sames = 1;
                for (t = x; t < 7; t++) {
                    if (this.box[t][y].type == this.box[t + 1][y].type) 
                        sames++;
                    else break;
                }
                if (sames >= 3) {
                    for (sames--, t = x; sames >= 0; sames--, t++) {
                        this.to_clear[t][y] = true;
                    }
                    result = true;
                }
                sames = 1;
                for (t = y; t < 8; t++) {
                    if (this.box[x][t].type == this.box[x][t + 1].type) 
                        sames++;
                    else break;
                }
                if (sames >= 3) {
                    for (sames--, t = y; sames >= 0; sames--, t++) {
                        this.to_clear[x][t] = true;
                    }
                    result = true;
                }
            }
        }
        return result;
    },
});
fruitbox = new FruitBox();

function game_loop(){
    fruitbox.OnUpdate();
    fruitbox.OnDraw();
}

addEvent("domready" , function(){
    var sns = $("fcanvas");
    ctx = sns.getContext("2d");
    sns.addEvent('mousedown', OnMouseDown);
	game_loop.periodical(66);
});
